@startuml
namespace controller {
    class Scheduler << (S,Aquamarine) >> {
        - task Task
        - properties configuration.SchedulerProperties
        - log *zap.SugaredLogger

        + Run()

    }
    class SynchronizationController << (S,Aquamarine) >> {
        - database *db.ProjectsRepository
        - kubernetes *k8s.Repository
        - generator *generator.Generator
        - properties configuration.Properties

        - handle(ctx context.Context, task db.Task, namespace internal.Namespace, existing namespaceIndex) (db.Task, bool, error)
        - getExistingNamespaces(ctx context.Context) (namespaceIndex, error)
        - createOrPossiblyUpdateTask(ctx context.Context, existing namespaceIndex, namespace internal.Namespace, task db.Task) (bool, error)
        - possiblySuspendTask(ctx context.Context, existing namespaceIndex, namespace internal.Namespace, task db.Task) error

        + Name() string
        + Execute(ctx context.Context) error

    }
    class SynchronizationLoggingController << (S,Aquamarine) >> {
        - database *db.ProjectsRepository
        - logging *logging.LoggingRepository
        - properties configuration.LoggingProperties

        - handle(ctx context.Context, cred *db.LoggingCredentials, task db.Task) (db.Task, bool, error)
        - onCreateLoggingResource(task *db.Task, cred *db.LoggingCredentials) ([]*logging.LoggingRequestResult, error)
        - onPatchLoggingResource(task *db.Task, cred *db.LoggingCredentials) ([]*logging.LoggingRequestResult, error)

        + Name() string
        + Execute(ctx context.Context) error

    }
    interface Task  {
        + Name() string
        + Execute( context.Context) error

    }
    class TaskMetricsController << (S,Aquamarine) >> {
        - log *zap.SugaredLogger
        - projects *db.ProjectsRepository
        - taskStatusGauge *prometheus.GaugeVec
        - taskClusterResourceStatusGauge *prometheus.GaugeVec

        + Name() string
        + Execute(ctx context.Context) error

    }
    class controller.namespaceIndex << (T, #FF7700) >>  {
    }
    class controllerHandlingResult << (S,Aquamarine) >> {
        - handled bool
        - err error

    }
    class generic << (S,Aquamarine) >> {
        - log *zap.SugaredLogger

        - withChannel(channel <font color=blue>chan</font> db.ProjectResult, block <font color=blue>func</font>(*db.Project) (bool, error)) error
        - handleResult(result db.ProjectResult, block <font color=blue>func</font>(*db.Project) (bool, error), results <font color=blue>chan</font> controllerHandlingResult)

    }
    class "<font color=blue>map</font>[internal.Namespace]*k8s.Namespace" as fontcolorbluemapfontinternalNamespacek8sNamespace {
        'This class was created so that we can correctly have an alias pointing to this name. Since it contains dots that can break namespaces
    }
}
"controller.generic" *-- "controller.SynchronizationController"
"controller.generic" *-- "controller.SynchronizationLoggingController"

"controller.Task" <|-- "controller.SynchronizationController"
"controller.Task" <|-- "controller.SynchronizationLoggingController"
"controller.Task" <|-- "controller.TaskMetricsController"

"controller.fontcolorbluemapfontinternalNamespacek8sNamespace" #.. "controller.namespaceIndex"
@enduml
